home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’95 / Desktop Pets / MenuPet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-28  |  18.9 KB  |  832 lines  |  [TEXT/MMCC]

  1. #include "MenuPet.h"
  2. #include <AppleEvents.h>
  3. #include <stdlib.h>
  4. #include <Icons.h>
  5. #include "LayerMgr.h"
  6. /*
  7.     Any parts written by me are Copyright 1995 Christopher Evans
  8.     All Rights Reserved.
  9. */
  10.  
  11. /*******************************************************************************
  12.  
  13.     The “g” prefix is used to emphasize that a variable is global.
  14.  
  15. *******************************************************************************/
  16.  
  17. SysEnvRec    gMac;                
  18. Boolean        gQuit;                
  19. Boolean        gInBackground;        
  20.  
  21. WindowPtr    GetDesktopWindow(void);
  22.  
  23. Point        lastPosition = {20,20};
  24. Point        destination = {120,15};
  25.  
  26. Rect        appleRect = {5, 15, 16, 30};
  27.  
  28. RGBColor     rgbBlack = {0,0,0};
  29. RGBColor    rgbWhite = {65535,65535, 65535};
  30.  
  31. unsigned long    goHUntil = 0;
  32. unsigned long    goVUntil = 0;
  33. unsigned long    lastSleepTime = 0;
  34. unsigned long    nextMoveTime = 0;
  35. Boolean    gStuck = false;
  36. short    stuckCount = 0;
  37.  
  38. #define MAX_STUCK_COUNT    60
  39. //#define BOTTOM_BOUNDS (GetMBarHeight() - 4)
  40. #define BOTTOM_BOUNDS (wmPort->portRect.bottom)
  41. #define MAX_REST    600        //In ticks
  42. #define PET_LAZINESS     -1
  43.  
  44. //#define LARGE_BUG    1
  45.  
  46. GrafPtr        petPort;
  47. RgnHandle    petRgnUp = nil;
  48. Handle        petSuiteUp = nil;
  49. RgnHandle    petRgnRt = nil;
  50. Handle        petSuiteRt = nil;
  51. RgnHandle    petRgnDn = nil;
  52. Handle        petSuiteDn = nil;
  53. RgnHandle    petRgnLt = nil;
  54. Handle        petSuiteLt = nil;
  55.  
  56. short        lastDirection = 0;
  57.  
  58. enum {
  59.     dirUp = 1,
  60.     dirRight,
  61.     dirDown,
  62.     dirLeft
  63. };
  64. /*******************************************************************************
  65.  
  66.     Define HiWrd and LoWrd macros for efficiency.
  67.  
  68. *******************************************************************************/
  69.  
  70. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  71. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  72. //#define abs(x)     ((x < 0) ? -(x) : x)
  73.  
  74. void InitToolbox(void);
  75. void MainEventLoop(void);
  76. void DeathAlert(short errNumber);
  77. void HandleEvent(EventRecord *event);
  78. Boolean    TrapExists(short theTrap);
  79. TrapType    GetTrapType(short theTrap);
  80. short    NumToolboxTraps(void);
  81. void CleanUp(void);
  82. void MoveMyPet(void);
  83. void HandleMouseDown(EventRecord *event);
  84. void HandleMenuCommand(long    menuResult);
  85. void HandleKeyPress(EventRecord *event);
  86. void AdjustMenus(void);
  87. Boolean    PtNearPet(Point pt);
  88.  
  89. /*******************************************************************************
  90.  
  91.     main
  92.  
  93.     Entry point for our program. We initialize the toolbox, make sure we are
  94.     running on a sufficiently studly machine, and put up the menubar. Finally,
  95.     we start polling for events and handling them by entering our main event
  96.     loop.
  97.  
  98. *******************************************************************************/
  99. main()
  100. {
  101.     GrafPtr    savePort;
  102.     /*    If you have stack requirements that differ from the default,
  103.         then you could use SetApplLimit to increase StackSpace at
  104.         this point, before calling MaxApplZone. */
  105.  
  106.     MaxApplZone();                    /* Expand the heap so code segments load
  107.                                        at the top */
  108.     InitToolbox();                    /* Initialize the program */
  109.     
  110.     {
  111. #ifdef LARGE_BUG
  112.         Rect    iconRect = {0,0,32,32};
  113.         GetIconSuite(&petSuiteUp, 1, svAllLargeData);
  114.         GetIconSuite(&petSuiteRt, 2, svAllLargeData);
  115.         GetIconSuite(&petSuiteDn, 3, svAllLargeData);
  116.         GetIconSuite(&petSuiteLt, 4, svAllLargeData);
  117.  
  118. #else
  119.         Rect    iconRect = {0,0,16,16};
  120.         GetIconSuite(&petSuiteUp, 1, svAllAvailableData);
  121.         GetIconSuite(&petSuiteRt, 2, svAllAvailableData);
  122.         GetIconSuite(&petSuiteDn, 3, svAllAvailableData);
  123.         GetIconSuite(&petSuiteLt, 4, svAllAvailableData);
  124. #endif
  125.         petRgnUp = NewRgn();
  126.         IconIDToRgn(petRgnUp, &iconRect, atBottom + atHorizontalCenter, 1);
  127.         petRgnRt = NewRgn();
  128.         IconIDToRgn(petRgnRt, &iconRect, atBottom + atHorizontalCenter, 2);
  129.         petRgnDn = NewRgn();
  130.         IconIDToRgn(petRgnDn, &iconRect, atBottom + atHorizontalCenter, 3);
  131.         petRgnLt = NewRgn();
  132.         IconIDToRgn(petRgnLt, &iconRect, atBottom + atHorizontalCenter, 4);
  133.     }
  134.  
  135.     GetPort(&savePort);
  136.     petPort = GetDesktopWindow();
  137.     MainEventLoop();                /* Call the main event loop */
  138.     SetPort(savePort);
  139. }
  140.  
  141.  
  142. /*******************************************************************************
  143.  
  144.     InitToolbox
  145.  
  146.     Set up the whole world, including global variables, Toolbox managers, and
  147.     menus.
  148.  
  149. *******************************************************************************/
  150. void InitToolbox()
  151. {
  152.     Handle        menuBar;
  153.     EventRecord event;
  154.     short        count;
  155.     long        gestaltResponse;
  156.     OSErr    myErr;
  157.  
  158.     gInBackground = FALSE;
  159.     gQuit = FALSE;
  160.  
  161.     InitGraf((Ptr) &qd.thePort);
  162.     InitFonts();
  163.     InitWindows();
  164.     InitMenus();
  165.     TEInit();
  166.     InitDialogs(NIL);
  167.     InitCursor();
  168.     
  169.     MoreMasters();
  170.     MoreMasters();
  171.  
  172.     GetDateTime((unsigned long *)&qd.randSeed);        //Initialize the random number generator
  173.  
  174.     /*    This next bit of code waits until MultiFinder brings our application
  175.         to the front. This gives us a better effect if we open a window at
  176.         startup. */
  177.  
  178. //    for (count = 1; count <= 3; ++count)
  179. //        EventAvail(everyEvent, &event);
  180.  
  181.     SysEnvirons(curSysEnvVers, &gMac);
  182.  
  183.     if (gMac.machineType < 0)
  184.         DeathAlert(errWimpyROMs);
  185.  
  186.     if (gMac.systemVersion < 0x0600)
  187.         DeathAlert(errWimpySystem);
  188.  
  189.     if (!TrapExists(_WaitNextEvent))
  190.         DeathAlert(errWeirdSystem);
  191.  
  192.  
  193.     menuBar = GetNewMBar(rMenuBar);            /* Read menus into menu bar */
  194.     if ( menuBar == NIL )
  195.          DeathAlert(errNoMenuBar);
  196.     SetMenuBar(menuBar);                    /* Install menus */
  197.     DisposHandle(menuBar);
  198.     AddResMenu(GetMHandle(mApple), 'DRVR');    /* Add DA names to Apple menu */
  199.     DrawMenuBar();
  200. }
  201.  
  202.  
  203. void DeathAlert(short errNumber)
  204. {
  205.     short        itemHit;
  206.     Str255        theMessage;
  207.  
  208.     SetCursor(&qd.arrow);
  209.     GetIndString(theMessage, rErrorStrings, errNumber);
  210.     ParamText(theMessage, NIL, NIL, NIL);
  211.     itemHit = StopAlert(rErrorAlert, NIL);
  212.     ExitToShell();
  213. }
  214.  
  215.  
  216.  
  217.  
  218. /*******************************************************************************
  219.  
  220.     MainEventLoop
  221.  
  222.     Get events forever, and handle them by calling HandleEvent. First, call
  223.     DoAdjustCursor to set our cursor shape, and to set the cursor region. We
  224.     then call WaitNextEvent() to get the event. This is OK, because we know
  225.     we’re running on System 6.0 or later by this time. If we got an event, we
  226.     handle it by calling HandleEvent(). But before doing that, we call
  227.     DoAdjustCursor again in case our application had fallen asleep under
  228.     MultiFinder.
  229.  
  230. *******************************************************************************/
  231. void MainEventLoop()
  232. {
  233.     RgnHandle    cursorRgn;
  234.     Boolean        gotEvent;
  235.     EventRecord    event;
  236.     Point        mouse;
  237.     long        lastFlagsCheck = 0, checkInterval;
  238.  
  239.     cursorRgn = NIL;
  240.     while ( !gQuit ) {
  241.  
  242.         gotEvent = WaitNextEvent(everyEvent, &event, (gInBackground?2:1), nil);
  243.         if ( gotEvent ) {
  244.             HandleEvent(&event);
  245.             MoveMyPet();
  246.         }
  247.         else{
  248.             MoveMyPet();
  249.         }
  250.     }
  251.     CleanUp();
  252. }
  253.  
  254.  
  255. /*******************************************************************************
  256.  
  257.     HandleEvent
  258.  
  259.     Do the right thing for an event. Determine what kind of event it is, and
  260.     call the appropriate routines.
  261.  
  262. *******************************************************************************/
  263. void HandleEvent(EventRecord *event)
  264. {
  265.     switch ( event->what ) {
  266.         case mouseDown:
  267.             HandleMouseDown(event);
  268.             break;
  269.         case keyDown:
  270.         case autoKey:
  271.             HandleKeyPress(event);
  272.             break;
  273.         case activateEvt:
  274. //            HandleActivate(event);
  275.             break;
  276.         case updateEvt:
  277. //            HandleUpdate(event);
  278.             break;
  279.         case diskEvt:
  280. //            HandleDiskInsert(event);
  281.             break;
  282.         case osEvt:
  283. //            HandleOSEvent(event);
  284.             break;
  285.         case kHighLevelEvent:
  286. //            AEProcessAppleEvent(event);
  287.             break;
  288.         default:
  289.             break;
  290.     }
  291. }
  292.  
  293. Boolean    TrapExists(short theTrap)
  294. {
  295.     TrapType    theTrapType;
  296.  
  297.     theTrapType = GetTrapType(theTrap);
  298.     if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
  299.         return false;
  300.     else
  301.         return (NGetTrapAddress(_Unimplemented, ToolTrap) !=
  302.                 NGetTrapAddress(theTrap, theTrapType));
  303. }
  304.  
  305.  
  306. /*******************************************************************************
  307.  
  308.     GetTrapType
  309.  
  310.     Check the bits of a trap number to determine its type. If bit 11 is set,
  311.     it’s a toolbox trap. Otherwise, it’s an OS trap.
  312.  
  313. *******************************************************************************/
  314. TrapType    GetTrapType(short theTrap)
  315. {
  316.     if ((theTrap & 0x0800) == 0)                    /* Per D.A. */
  317.         return (OSTrap);
  318.     else
  319.         return (ToolTrap);
  320. }
  321.  
  322.  
  323. /*******************************************************************************
  324.  
  325.     NumToolboxTraps
  326.  
  327.     Find the size of the Toolbox trap table. This can be either 0x0200 or
  328.     0x0400 bytes, depending on which Macintosh we are running on. We determine
  329.     the size by taking advantage of an anomaly of the smaller trap table: any
  330.     entries that fall beyond the end of the table are mirrored back down into
  331.     the lower part. For example, on a large table, trap numbers A86E and AA6E
  332.     correspond to different routines. However, on a small table, they
  333.     correspond to the same routine. By checking the addresses of these
  334.     routines, we can determine the size of the table.
  335.  
  336. *******************************************************************************/
  337. short    NumToolboxTraps(void)
  338. {
  339.     if (NGetTrapAddress(0xA86E, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  340.         return (0x200);
  341.     else
  342.         return (0x400);
  343. }
  344.  
  345.  
  346. void CleanUp(void)
  347. {
  348.  
  349. }
  350.  
  351. void HandleMouseDown(EventRecord *event)
  352. {
  353.     long        newSize;
  354.     Rect        growRect;
  355.     WindowPtr    theWindow;
  356.     short        part = FindWindow(event->where, &theWindow);
  357.     GrafPtr        savePort;
  358.     
  359.     switch ( part ) {
  360.         case inMenuBar:                /* Process a mouse menu command (if any) */
  361.             AdjustMenus();
  362.             HandleMenuCommand(MenuSelect(event->where));
  363. //            if(PtInRgn(event->where,petRgn)) {
  364. //                SysBeep(10);
  365. //            }
  366.             break;
  367.         case inSysWindow:            /* Let the system handle the mouseDown */
  368.             SystemClick(event, theWindow);
  369.             break;
  370.         case inContent:
  371.             break;
  372.  
  373.         case inDrag:                /* Pass screenBits.bounds to get all gDevices */
  374.             break;
  375.  
  376.         case inGrow:
  377.             break;
  378.         case inGoAway:
  379.             break;
  380.         case inZoomIn:
  381.         case inZoomOut:
  382.             break;
  383.     }
  384. }
  385.  
  386.  
  387. void HandleMenuCommand(menuResult)
  388.     long        menuResult;
  389. {
  390.     short        menuID;                /* The resource ID of the selected menu */
  391.     short        menuItem;            /* The item number of the selected menu */
  392.     Str255        daName;
  393.     WindowPtr    window;
  394.     MenuHandle    menu;
  395.     ModalFilterUPP    aboutFilter;
  396.     
  397.     menuID = HiWrd(menuResult);
  398.     menuItem = LoWrd(menuResult);
  399.     switch ( menuID ) {
  400.         case mApple:
  401.             switch ( menuItem ) {
  402.                 case iAbout:
  403.                     break;
  404.                 default:            /* All non-About items in this menu are DAs */
  405.                     GetItem(GetMHandle(mApple), menuItem, daName);
  406.                     (void) OpenDeskAcc(daName);
  407.                     break;
  408.             }
  409.             break;
  410.         case mFile:
  411.             switch ( menuItem ) {
  412.                 case iNew:
  413.                     /* DoNewWindow(); */
  414.                     AdjustMenus();
  415.                     DrawMenuBar();
  416.                     break;
  417.                 case iOpen:
  418.                     break;
  419.                 case iClose:
  420.                     break;
  421.                 
  422.                 case iSave:
  423.                     break;
  424.                     
  425.                 case iSaveAs:
  426.                     break;
  427.                     
  428.                 case iQuit:
  429.                     gQuit = TRUE;
  430.                     break;
  431.             }
  432.             break;
  433.         case mEdit:
  434.             switch (menuItem) {
  435.                 /* Call SystemEdit for DA editing & MultiFinder */
  436.                 /* since we don’t do any Editing */
  437.                 case iUndo:
  438.                 case iCut:
  439.                 case iCopy:
  440.                 case iPaste:
  441.                     break;
  442.             }
  443.     }
  444.     HiliteMenu(0);        /* Unhighlight what MenuSelect or MenuKey hilited */
  445. }
  446.  
  447. /*******************************************************************************
  448.  
  449.     HandleKeyPress
  450.  
  451.     The user pressed a key. What are you going to do about it?
  452.  
  453. *******************************************************************************/
  454. void HandleKeyPress(EventRecord *event)
  455. {
  456.     char    key;
  457.  
  458.     key = event->message & charCodeMask;
  459.     if ( event->modifiers & cmdKey ) {        /* Command key down? */
  460.         AdjustMenus();                        /* Enable/disable/check menu items properly */
  461.         HandleMenuCommand(MenuKey(key));
  462.     } else {
  463.         if(key == '?') {
  464.             GrafPtr    wmPort, savePort;
  465.             RgnHandle    showRgn = NewRgn();
  466.             Rect        showRect;
  467.             long    junkLong;
  468.             
  469.             GetPort(&savePort);
  470. //            GetWMgrPort(&wmPort);
  471.             wmPort = (GrafPtr)petPort;
  472.             SetPort(wmPort);
  473.             
  474.             switch(lastDirection) {
  475.                 case dirUp:
  476.                     CopyRgn(petRgnUp, showRgn);
  477.                     break;
  478.                 case dirLeft:
  479.                     CopyRgn(petRgnLt, showRgn);
  480.                     break;
  481.                 case dirDown:
  482.                     CopyRgn(petRgnDn, showRgn);
  483.                     break;
  484.                 case dirRight:
  485.                     CopyRgn(petRgnRt, showRgn);
  486.                     break;
  487.                 default:
  488.                     CopyRgn(petRgnUp, showRgn);
  489.             }
  490.             OffsetRgn(showRgn,lastPosition.h,lastPosition.v);
  491.  
  492.             InsetRgn(showRgn,-1,-1);
  493.             InvertRgn(showRgn);
  494.             Delay(5, &junkLong );        //OSUtils.h
  495.             InvertRgn(showRgn);
  496.             Delay(5, &junkLong );        //OSUtils.h
  497.             InvertRgn(showRgn);
  498.             Delay(5, &junkLong );        //OSUtils.h
  499.             InvertRgn(showRgn);
  500.             SetPort(savePort);
  501.             DisposeRgn(showRgn);
  502.         }
  503.         if(key == 'z') {
  504.             GrafPtr    wmPort, savePort;
  505.             GetPort(&savePort);
  506. //            GetCWMgrPort((CGrafPtr *)&wmPort);
  507.             wmPort = (GrafPtr)petPort;
  508.             SetPort(wmPort);
  509.             InvalRect(&wmPort->portRect);
  510.             
  511.             SetPort(savePort);
  512.         }
  513.         /* DoKeyPress(event) */;
  514.     }
  515. }
  516.  
  517. void AdjustMenus()
  518. {
  519.  
  520. }
  521.  
  522. Boolean    PtNearPet(Point pt)
  523. {
  524.     Rect    showRect;
  525.     Boolean        result;
  526.     
  527.     SetRect(&showRect, lastPosition.h, lastPosition.v, lastPosition.h+4, lastPosition.v+4);
  528.     
  529.     InsetRect(&showRect, -20 , -20);
  530.     
  531.     result = PtInRect(pt, &showRect);
  532.     
  533.     return result;
  534. }
  535.  
  536.  
  537.  
  538.  
  539. void    MoveMyPet(void)
  540. {
  541.     GrafPtr    savePort, wmPort;
  542.     RgnHandle    oldPetRgn, newPetRgn, updateRgn;
  543.     Boolean    goH = false, goV = false;
  544.     Point    mouseLoc;
  545.     unsigned long    curTick = TickCount();
  546.     Point    oldPosition = lastPosition;
  547.     OSErr    theErr;
  548. #ifdef LARGE_BUG
  549.     Rect    iconRect = {0,0,32,32};
  550. #else
  551.     Rect    iconRect = {0,0,16,16};
  552. #endif
  553.     
  554.     if(PET_LAZINESS > 0) {
  555.         if(curTick % PET_LAZINESS != 0) {
  556.             return;
  557.         }
  558.     }
  559.     
  560.     
  561.     GetPort(&savePort);
  562. //    GetWMgrPort(&wmPort);
  563.     GetCWMgrPort((CGrafPtr *)&wmPort);
  564.     wmPort = (GrafPtr)petPort;
  565.     
  566.     SetPort(wmPort);
  567.     if(curTick < nextMoveTime) {
  568.     
  569.         OffsetRect(&iconRect,lastPosition.h,lastPosition.v);
  570.         switch(lastDirection) {
  571.             case dirUp:
  572.                 theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttDisabled, petSuiteUp);
  573.                 break;
  574.             case dirLeft:
  575.                 theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttDisabled, petSuiteLt);
  576.                 break;
  577.             case dirDown:
  578.                 theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttDisabled, petSuiteDn);
  579.                 break;
  580.             case dirRight:
  581.                 theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttDisabled, petSuiteRt);
  582.                 break;
  583.             default:
  584.                 theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttDisabled, petSuiteUp);
  585.         }
  586.         SetPort(savePort);
  587.         return;
  588.     }
  589.     
  590.     GetMouse(&mouseLoc);
  591.     
  592.     RGBForeColor(&rgbWhite);
  593.     
  594.     
  595.     if(goHUntil > curTick) {
  596.         goH = true;
  597.     }
  598.     else {
  599.         if(Random() %5 == 0) {
  600.             goHUntil = curTick + (60 * (abs(Random()) % 5)); 
  601.         }
  602.     }
  603.  
  604.     if(goVUntil > curTick) {
  605.         goV = true;
  606.     }
  607.     else {
  608.         if(Random() %10 == 0) {
  609.             goVUntil = curTick + (60 * (abs(Random()) % 3)); 
  610.         }
  611.     }
  612.  
  613.     if(mouseLoc.v < GetMBarHeight()) {
  614.         goH = true;
  615.     }
  616.     
  617.     if(goH) {
  618.         if(PtNearPet(mouseLoc) ){
  619.             if( lastPosition.h > mouseLoc.h ) {
  620.                 lastPosition.h += 2;
  621.                 if(lastPosition.h > wmPort->portRect.right) {
  622.                     lastPosition.h -= 2;
  623.                 }
  624.             }
  625.             else {
  626.                 lastPosition.h -= 2;
  627.                 if(lastPosition.h < wmPort->portRect.left) {
  628.                     lastPosition.h += 2;
  629.                 }
  630.             }
  631.             
  632.         }
  633.         else {
  634.             if(destination.h > lastPosition.h) {
  635.                 lastPosition.h ++;
  636.                 if(lastPosition.h > wmPort->portRect.right) {
  637.                     lastPosition.h -= 1;
  638.                 }
  639.             }
  640.             if(destination.h < lastPosition.h) {
  641.                 lastPosition.h -= 1;
  642.                 if(lastPosition.h < wmPort->portRect.left) {
  643.                     lastPosition.h += 1;
  644.                 }
  645.             }
  646.         }
  647.     }
  648.     
  649.     if((destination.h == lastPosition.h && destination.v == lastPosition.v) || stuckCount == MAX_STUCK_COUNT){
  650.         if(stuckCount != MAX_STUCK_COUNT) {
  651.             nextMoveTime = lastSleepTime = curTick + (abs(Random()) % MAX_REST);
  652.         }
  653.     //    else {
  654.     //        DebugStr("\presetting 'cuz stuck");
  655.     //     }    
  656.         destination.h = wmPort->portRect.left  + abs(Random() % (wmPort->portRect.right - wmPort->portRect.left));
  657.         destination.v = wmPort->portRect.top + abs(Random() % (wmPort->portRect.bottom - wmPort->portRect.top));
  658.         {
  659.             long    longPt = PinRect(&petPort->portRect, destination);   /* IM I pg 293 */
  660.             destination = *((Point *)&longPt);
  661.         }
  662.         stuckCount = 0;    //when we decide to go somewhere else, reset the stuck count in case we were stuck.
  663.     }
  664.     
  665.     if(goV) {
  666.         if(destination.v > lastPosition.v) {
  667.             lastPosition.v ++;
  668.             if(lastPosition.v > BOTTOM_BOUNDS) {
  669.                 lastPosition.v --;
  670.             }
  671.         }
  672.         else {
  673.             if(destination.v < lastPosition.v) {
  674.                 lastPosition.v --;
  675.                 if(lastPosition.v < 0) {
  676.                     lastPosition.v ++;
  677.                 }
  678.             }
  679.         }
  680.     }
  681.     
  682.     if(gStuck) {
  683.         
  684.         if(destination.v < lastPosition.v) {
  685.             destination.v++;
  686.         }
  687.         else {
  688.             destination.v --;
  689.         }
  690.         if(destination.h < lastPosition.h) {
  691.             destination.h++;
  692.         }
  693.         else {
  694.             destination.h --;
  695.         }
  696.     //    stuckCount ++;
  697.     }
  698.     
  699.     { 
  700.         long    longPt = PinRect(&petPort->portRect, lastPosition);   /* IM I pg 293 */
  701.         Point    tmpPosition; 
  702.         tmpPosition.h +=  8;
  703.         tmpPosition.v +=  8;
  704.         
  705.         lastPosition = *((Point *)&longPt);
  706.         tmpPosition = lastPosition;
  707.         //if(!PtInRgn(tmpPosition, petPort->visRgn)) {
  708.         //    lastPosition = oldPosition;
  709.         //    if(!gStuck) stuckCount = 0;
  710.         //    gStuck = true;
  711.         //}
  712.         //else {
  713.         //    gStuck = false;
  714.         //}
  715.     }
  716.     
  717.     RGBForeColor(&rgbBlack);
  718.  
  719.     oldPetRgn = NewRgn();
  720.     newPetRgn = NewRgn();
  721.     updateRgn = NewRgn();
  722.     
  723.     switch(lastDirection) {
  724.         case dirUp:
  725.             CopyRgn(petRgnUp, oldPetRgn);
  726.             break;
  727.         case dirLeft:
  728.             CopyRgn(petRgnLt, oldPetRgn);
  729.             break;
  730.         case dirDown:
  731.             CopyRgn(petRgnDn, oldPetRgn);
  732.             break;
  733.         case dirRight:
  734.             CopyRgn(petRgnRt, oldPetRgn);
  735.             break;
  736.         default:
  737.             CopyRgn(petRgnUp, oldPetRgn);
  738.     }
  739.     OffsetRgn(oldPetRgn,oldPosition.h,oldPosition.v);
  740.     
  741.     if(oldPosition.h > lastPosition.h) {    //Going left
  742.         if(oldPosition.v > lastPosition.v) {    //Going up
  743.             lastDirection = dirLeft;
  744.         }
  745.         else {    //Going down
  746.             lastDirection = dirDown;
  747.         }
  748.     }
  749.     else {    //Going right
  750.         if(oldPosition.v > lastPosition.v) {    //Going up
  751.             lastDirection = dirUp;
  752.         }
  753.         else {    //Goung down
  754.             lastDirection = dirRight;
  755.         }    
  756.     }
  757.     
  758.     switch(lastDirection) {
  759.         case dirUp:
  760.             CopyRgn(petRgnUp, newPetRgn);
  761.             break;
  762.         case dirLeft:
  763.             CopyRgn(petRgnLt, newPetRgn);
  764.             break;
  765.         case dirDown:
  766.             CopyRgn(petRgnDn, newPetRgn);
  767.             break;
  768.         case dirRight:
  769.             CopyRgn(petRgnRt, newPetRgn);
  770.             break;
  771.         default:
  772.             CopyRgn(petRgnUp, newPetRgn);
  773.     }
  774.     OffsetRgn(newPetRgn,lastPosition.h,lastPosition.v);
  775.     
  776.     DiffRgn(oldPetRgn, newPetRgn, updateRgn);
  777. //    EraseRgn(updateRgn);
  778.     InvalRgn(updateRgn);
  779.  
  780.     OffsetRect(&iconRect,lastPosition.h,lastPosition.v);
  781.     switch(lastDirection) {
  782.         case dirUp:
  783.             theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttNone, petSuiteUp);
  784.             break;
  785.         case dirLeft:
  786.             theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttNone, petSuiteLt);
  787.             break;
  788.         case dirDown:
  789.             theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttNone, petSuiteDn);
  790.             break;
  791.         case dirRight:
  792.             theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttNone, petSuiteRt);
  793.             break;
  794.         default:
  795.             theErr = PlotIconSuite(&iconRect, atBottom + atHorizontalCenter, ttNone, petSuiteUp);
  796.     }
  797.     LMSetPaintWhite(TRUE);    //Lowmem.h
  798.     LMSetSaveUpdate(TRUE);
  799.     PaintOne((WindowRef)petPort, updateRgn);
  800.     PaintBehind((WindowRef)petPort, updateRgn);
  801.  
  802.  
  803.     DisposeRgn(oldPetRgn);
  804.     DisposeRgn(newPetRgn);
  805.     DisposeRgn(updateRgn);
  806. //    InvertRgn(petRgn);
  807.     
  808.     SetPort(savePort);
  809. }
  810.  
  811. WindowPtr    GetDesktopWindow(void)
  812. {
  813.     WindowPtr desktopWindow;
  814.     Str255    wTitle;
  815.     
  816.     desktopWindow = GetFrontWindowForSignature('FNDR');
  817.     if(desktopWindow) {
  818.         while( desktopWindow ) {
  819.             GetWTitle(desktopWindow, wTitle);
  820.             if(RelString(wTitle, "\pDesktop", true, true) == 0) {   /* IM IV pg 234 */
  821.                 return desktopWindow;
  822.             }
  823.             desktopWindow = (WindowPtr)((WindowPeek)desktopWindow)->nextWindow;
  824.         }
  825.     }
  826.     return nil;
  827.  
  828. }
  829.  
  830.  
  831.  
  832.